﻿/************************************************************************

   Extended Silverlight Toolkit

   Copyright (C) 2010-2012 Xceed Software Inc.

   This program is provided to you under the terms of the Microsoft Public
   License (Ms-PL) as published at http://extendedsilverlight.codeplex.com/license

   Please purchase a commercial version of this toolkit if you are using
   it in a commercial product. The commercial versions support the project,
   and also include more features for each control, priority support,
   source code, updates, removed watermark, and a proprietary license.

   Visit http://xceed.com and follow @datagrid on Twitter.

  **********************************************************************/

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;

namespace Xceed.Silverlight.DataGrid
{
  internal sealed class VisualStateHelper
  {
    #region Constructor

    internal VisualStateHelper( Control owner )
    {
      if( owner == null )
        throw new ArgumentNullException( "owner" );

      m_owner = owner;
    }

    #endregion

    #region Owner Private Property

    private Control Owner
    {
      get
      {
        return m_owner;
      }
    }

    private readonly Control m_owner;

    #endregion

    #region VisualStates Private Property

    private IDictionary<StateType, string> VisualStates
    {
      get
      {
        return m_visualStates;
      }
    }

    private readonly Dictionary<StateType, string> m_visualStates = new Dictionary<StateType, string>();

    #endregion

    #region VisualStatesAppliedOnce Private Property

    private bool VisualStatesAppliedOnce
    {
      get
      {
        return m_visualStatesAppliedOnce;
      }
    }

    private void VisualStatesApplied()
    {
      m_visualStatesAppliedOnce = true;
    }

    private bool m_visualStatesAppliedOnce;

    #endregion

    #region VisualStatesVersion Private Property

    private int VisualStatesVersion
    {
      get
      {
        return m_visualStatesVersion;
      }
    }

    private void SetNewVisualStatesVersion()
    {
      unchecked
      {
        m_visualStatesVersion++;
      }
    }

    private int m_visualStatesVersion;

    #endregion

    #region Goto State Methods

    internal void GoToCommonState( string state, bool useTransitions )
    {
      this.SetVisualState( StateType.Common, state, useTransitions );
    }

    internal void GoToCurrentState( string state, bool useTransitions )
    {
      this.SetVisualState( StateType.Current, state, useTransitions );
    }

    internal void GoToGroupNavigationSearchBoxVisibilityState( string state, bool useTransitions )
    {
      this.SetVisualState( StateType.GroupNavigationSearchBoxVisibility, state, useTransitions );
    }

    internal void GoToGroupNavigationButtonsVisibilityState( string state, bool useTransitions )
    {
      this.SetVisualState( StateType.GroupNavigationButtonsVisibility, state, useTransitions );
    }

    internal void GoToGroupExpansionButtonsVisibilityState( string state, bool useTransitions )
    {
      this.SetVisualState( StateType.GroupExpansionButtonsVisibility, state, useTransitions );
    }

    internal void GoToGroupExpansionState( string state, bool useTransitions )
    {
      this.SetVisualState( StateType.GroupExpansion, state, useTransitions );
    }

    internal void GoToFixedColumnToggleButtonVisibleState( string state, bool useTransitions )
    {
      this.SetVisualState( StateType.FixedColumnToggleButtonVisible, state, useTransitions );
    }

    internal void GoToFixedColumnToggleButtonState( string state, bool useTransitions )
    {
      this.SetVisualState( StateType.FixedColumnToggleButtonState, state, useTransitions );
    }

    internal void GoToFilterState( string state, bool useTransitions )
    {
      this.SetVisualState( StateType.Filter, state, useTransitions );
    }

    internal void GoToEditingState( string state, bool useTransitions )
    {
      this.SetVisualState( StateType.Editing, state, useTransitions );
    }

    internal void GoToValidationState( string state, bool useTransitions )
    {
      this.SetVisualState( StateType.Validation, state, useTransitions );
    }

    internal void GoToReadOnlyState( string state, bool useTransitions )
    {
      this.SetVisualState( StateType.ReadOnly, state, useTransitions );
    }

    internal void GoToSortingState( string state, bool useTransitions )
    {
      this.SetVisualState( StateType.Sorting, state, useTransitions );
    }

    internal void GoToRemoveButtonVisibilityState( string state, bool useTransitions )
    {
      this.SetVisualState( StateType.RemoveButtonVisibility, state, useTransitions );
    }

    internal void GoToLocationState( string state, bool useTransitions )
    {
      this.SetVisualState( StateType.Location, state, useTransitions );
    }

    internal void GoToIsEstimateState( string state, bool useTransitions )
    {
      this.SetVisualState( StateType.IsEstimate, state, useTransitions );
    }

    internal void GoToVisibilityState( string state, bool useTransitions )
    {
      this.SetVisualState( StateType.Visibility, state, useTransitions );
    }

    internal void GoToInitializationState( string state, bool useTransitions )
    {
      this.SetVisualState( StateType.Initialization, state, useTransitions );
    }

    internal void GoToLicensedState( string state, bool useTransitions )
    {
      this.SetVisualState( StateType.Licensed, state, useTransitions );
    }

    internal void GoToRequestPendingState( string state, bool useTransitions )
    {
      this.SetVisualState( StateType.RequestPending, state, useTransitions );
    }

    internal void GoToUnconstrainedState( string state, bool useTransitions )
    {
      this.SetVisualState( StateType.Unconstrained, state, useTransitions );
    }

    internal void GoToWatermarkVisibilityState( string state, bool useTransitions )
    {
      this.SetVisualState( StateType.WatermarkVisibility, state, useTransitions );
    }

    #endregion

    internal void ApplyVisualStates()
    {
      bool reapply = false;

      do
      {
        int version = this.VisualStatesVersion;

        foreach( var state in this.VisualStates.Values )
        {
          this.ApplyVisualState( state, this.VisualStatesAppliedOnce );

          reapply = ( version != this.VisualStatesVersion );
          if( reapply )
            break;
        }
      }
      while( reapply );

      this.VisualStatesApplied();
    }

    private void ApplyVisualState( string state, bool useTransitions )
    {
      VisualStateManager.GoToState( this.Owner, state, useTransitions );
    }

    private void SetVisualState( StateType type, string state, bool useTransitions )
    {
      if( string.IsNullOrEmpty( state ) )
      {
        if( this.VisualStates.Remove( type ) )
        {
          this.SetNewVisualStatesVersion();
        }
      }
      else
      {
        string currentState;
        if( ( !this.VisualStates.TryGetValue( type, out currentState ) )
          || ( currentState != state ) )
        {
          this.VisualStates[ type ] = state;
          this.SetNewVisualStatesVersion();
        }

        if( this.VisualStatesAppliedOnce )
        {
          this.ApplyVisualState( state, useTransitions );
        }
      }
    }

    #region StateType Nested Type

    private enum StateType
    {
      Common = 0,
      Current,
      GroupNavigationSearchBoxVisibility,
      GroupNavigationButtonsVisibility,
      GroupExpansionButtonsVisibility,
      GroupExpansion,
      FixedColumnToggleButtonVisible,
      FixedColumnToggleButtonState,
      Filter,
      Editing,
      Validation,
      ReadOnly,
      Sorting,
      RemoveButtonVisibility,
      Location,
      IsEstimate,
      Visibility,
      Initialization,
      Licensed,
      RequestPending,
      Unconstrained,
      WatermarkVisibility
    }

    #endregion
  }
}
